package com.zb.zeus.common.datascope.aspect;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.zb.zeus.common.core.utils.StringUtils;
import com.zb.zeus.common.core.web.domain.BaseEntity;
import com.zb.zeus.common.datascope.annotation.DataScope;
import com.zb.zeus.common.security.service.TokenHolderService;
import com.zb.zeus.system.api.domain.SysEmployee;
import com.zb.zeus.system.api.model.LoginUser;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Set;

/**
 * 数据过滤处理
 *
 * @author zb.zeus
 */
@Aspect
@Component
public class DataScopeAspect {

    /**
     * 数据权限过滤关键字
     */
    public static final String DATA_SCOPE = "dataScope";

    @Autowired
    private TokenHolderService tokenHolderService;

    // 配置织入点
    @Pointcut("@annotation(com.zb.zeus.common.datascope.annotation.DataScope)")
    public void dataScopePointCut() {
    }

    @Before("dataScopePointCut()")
    public void doBefore(JoinPoint point) throws Throwable {
        clearDataScope(point);
        handleDataScope(point);
    }

    protected void handleDataScope(final JoinPoint joinPoint) {
        // 获得注解
        DataScope controllerDataScope = getAnnotationLog(joinPoint);
        if (controllerDataScope == null) {
            return;
        }
        // 获取当前的用户
        LoginUser loginUser = tokenHolderService.getLoginUser();
        if (StringUtils.isNotNull(loginUser)) {
            SysEmployee currentEmployee = loginUser.getEmployee();
            // 如果是超级管理员，则不过滤数据
            if (StringUtils.isNotNull(currentEmployee) && !currentEmployee.isAdmin()) {
                dataScopeFilter(joinPoint, currentEmployee, controllerDataScope.orgAlias());
            }
        }
    }

    /**
     * 数据范围过滤
     *
     * @param joinPoint 切点
     * @param employee      用户
     * @param orgAlias  组织别名
     */
    public static void dataScopeFilter(JoinPoint joinPoint, SysEmployee employee, String orgAlias) {
        StringBuilder sqlString = new StringBuilder();
        Set<String> orgBusinessIds = employee.getOrgBusinessIds();
        //如果用户分配了自定义组织，用户有且仅有对应的自定义组织权限，反之按照用户所属ihr组织关联的自定义组织分配组织及组织以下权限
        if (CollectionUtils.isNotEmpty(orgBusinessIds)) {
            StringBuilder orgStr = new StringBuilder();
            for (String orgBusinessId : orgBusinessIds) {
                orgStr.append(orgBusinessId + ",");
            }
            sqlString.append(StringUtils.format(
                    " OR {}.id IN ( " + orgStr.substring(0, orgStr.length() - 1) + " )",
                    orgAlias));
        } else {
            sqlString.append(StringUtils.format(
                    " OR {}.id IN (SELECT tmp.id FROM ( " +
                            "SELECT tsob.id,tso.full_path FROM t_sys_org tso " +
                            "INNER JOIN t_sys_org_business_ihr tsobi on tso.id = tsobi.org_id " +
                            "INNER JOIN t_sys_org_business tsob on tsobi.business_id=tsob.id ) tmp " +
                            "WHERE find_in_set( {} , tmp.full_path ) )",
                    orgAlias, employee.getOrgId()));
        }


        if (StringUtils.isNotBlank(sqlString.toString())) {
            Object params = joinPoint.getArgs()[0];
            if (StringUtils.isNotNull(params) && params instanceof BaseEntity) {
                BaseEntity baseEntity = (BaseEntity) params;
                baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
            }
        }
    }

    /**
     * 是否存在注解，如果存在就获取
     */
    private DataScope getAnnotationLog(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method != null) {
            return method.getAnnotation(DataScope.class);
        }
        return null;
    }

    /**
     * 拼接权限sql前先清空params.dataScope参数防止注入
     */
    private void clearDataScope(final JoinPoint joinPoint) {
        Object params = joinPoint.getArgs()[0];
        if (StringUtils.isNotNull(params) && params instanceof BaseEntity) {
            BaseEntity baseEntity = (BaseEntity) params;
            baseEntity.getParams().put(DATA_SCOPE, "");
        }
    }
}
